﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace CommonHelper
{
    /// <summary>
    /// 将DataTable数据源转换成实体类
    /// </summary>
    /// <typeparam name="T">实体</typeparam>
    public static class DataTableToModel<T> where T: new()
    {

        /// <summary>
        /// 将DataTable数据源转换成实体类
        /// </summary>
        public static List<T> ToModel(DataTable dt)
        {
            List<T> ts = new List<T>();
            foreach (DataRow dr in dt.Rows)
            {
                T t = new T();
                PropertyInfo[] propertys = t.GetType().GetProperties();// 获得此模型的公共属性
                foreach (PropertyInfo pi in propertys)
                {
                    if (dt.Columns.Contains(pi.Name))
                    {
                        if (!pi.CanWrite) continue;
                        var value = dr[pi.Name];
                        if (value != DBNull.Value)
                        {
                            switch (pi.PropertyType.FullName)
                            {
                                case "System.Decimal":
                                    pi.SetValue(t, decimal.Parse(value.ToString()), null);
                                    break;
                                case "System.String":
                                    pi.SetValue(t, value.ToString(), null);
                                    break;
                                case "System.Int32":
                                    pi.SetValue(t, int.Parse(value.ToString()), null);
                                    break;
                                default:
                                    pi.SetValue(t, value, null);
                                    break;
                            }
                        }
                    }
                }
                ts.Add(t);
            }
            return ts;
        }


        /// <summary>
        /// DataRow 转 Model 对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="row"></param>
        /// <returns></returns>
        public static T DataRow2Model<T>(DataRow row)
        {
            T t = System.Activator.CreateInstance<T>();
            var ModelType = typeof(T);
            var Properties = ModelType.GetProperties();
            foreach (var Propertie in Properties)
            {
                if (Propertie.CanRead && Propertie.CanWrite)
                {
                    if (row.Table.Columns.Contains(Propertie.Name) && row[Propertie.Name] != DBNull.Value)
                    {
                        object value = row[Propertie.Name];
                        //如果非空，则赋给对象的属性 
                        if (value != DBNull.Value)
                        {
                            if (Propertie.GetMethod.ReturnParameter.ParameterType.Name == "Int32")
                            {
                                value = Convert.ToInt32(value);
                            }
                            Propertie.SetValue(t, value, null);
                        }
                        else
                        {
                            Propertie.SetValue(t, null);
                        }
                    }
                }
            }
            return t;
        }


        /// <summary>
        /// DataTable 转 Modle List
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="table"></param>
        /// <returns></returns>
        public static List<T> DataTable2ModelList<T>(DataTable table)
        {
            var list = new List<T>();
            foreach (DataRow row in table.Rows)
            {
                list.Add(DataRow2Model<T>(row));
            }
            return list;
        }


        /// <summary>
        /// 将DataTable中的数据封装到List<Model>集合中。
        /// </summary>
        /// <typeparam name="T">实体类型Model</typeparam>
        /// <param name="dt">需要转换的DataTable数据表</param>
        /// <returns>返回List<Model></returns>
        /// <exception cref="Exception"></exception>
        public static List<T> ToList<T>(DataTable dt)
        {
            try
            {
                List<T> list = new List<T>();
                Type type = typeof(T);
                List<PropertyInfo> plist = new List<PropertyInfo>(type.GetProperties());
                if (dt != null)
                {
                    foreach (DataRow row in dt.Rows)
                    {
                        //T t = (T)Activator.CreateInstance(type);
                        T t = Activator.CreateInstance<T>();
                        foreach (DataColumn dc in dt.Columns)
                        {
                            PropertyInfo pInfo = plist.Find(p => p.Name == dc.ColumnName);
                            if (pInfo != null)
                            {
                                if (!Convert.IsDBNull(row[pInfo.Name]))
                                {
                                    //pInfo.SetValue(t, row[colm.ColumnName], null);
                                    pInfo.SetValue(t, row[pInfo.Name], null);
                                }
                            }
                        }
                        list.Add(t);
                    }
                }
                return list;
            }
            catch (Exception ex)
            {

                throw new Exception(ex.Message);
            }
        }


        /// <summary>
        /// 将DataRow数据行转换为Model实体
        /// </summary>
        /// <typeparam name="T">Model实体的类型</typeparam>
        /// <param name="dr">需要转换的DataRow数据行</param>
        /// <returns>返回Model实体</returns>
        /// <exception cref="Exception"></exception>
        public static T ToModel<T>(DataRow dr)
        {
            try
            {
                Type type = typeof(T);//获得类型
                T model = (T)Activator.CreateInstance(type);//获得实体类
                List<PropertyInfo> plist = type.GetProperties().ToList();
                foreach (DataColumn dc in dr.Table.Columns)
                {
                    PropertyInfo pinfo = plist.Find(p => p.Name == dc.ColumnName);
                    if (pinfo != null)
                    {
                        if (!Convert.IsDBNull(dr[dc.ColumnName]))
                        {
                            pinfo.SetValue(model, dr[dc.ColumnName], null);
                        }
                    }
                }
                return model;
            }
            catch (Exception ex)
            {

                throw new Exception(ex.ToString());
            }
        }





    }
}
